﻿// CrashDump.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>
#include <Shlwapi.h>
#include <DbgHelp.h>
#include <sstream>

#pragma comment(lib, "Dbghelp.lib")
#pragma comment(lib, "shlwapi.lib")

std::wstring FormatString(const wchar_t *fmt, ...);

void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS* pException)
{
    // 创建Dump文件
    //
    HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    //
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    //
    //MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithFullMemory, &dumpInfo, NULL, NULL);
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);
}

std::wstring CrashDumpFile(PEXCEPTION_POINTERS pep)
{
    // SYSTEMTIME:
    // wMonth: 1-based
    // wDayOfWeek: 0: 周日, 1:周 一, 2: 周二, ... 6: 周六
    // wDay: 1－31
    // wHour: 24小时格式, 0－23
    // wMinute: 0－59
    // wSecond: 0－59

    SYSTEMTIME st;
    GetLocalTime(&st);

    wchar_t sExePath[MAX_PATH];
    GetModuleFileName(NULL, sExePath, MAX_PATH);
    PathRemoveFileSpec(sExePath);

    std::wstringstream sstream;
    sstream << ".//dump__" 
        << st.wYear << "_"
        << st.wMonth  << "_"
        << st.wDay  << "_"
        << st.wHour << "_"
        << st.wMinute << "_"
        << st.wSecond  << "_"
        << ".dump";
    std::wstring formated_str = sstream.str();

    std::wstring strDumpFile(sExePath);
    strDumpFile += formated_str;

    CreateDumpFile(strDumpFile.c_str(), pep);

    return strDumpFile;
}

static long ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
    std::wstring strFile = CrashDumpFile(pException);

    // 这里弹出一个错误对话框并退出程序
    std::wstring sInfo = std::wstring(L"Unhandled Exception! \r\nThe process is dumped to \r\n")  + strFile;
    FatalAppExit(0, sInfo.c_str());

    return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
    // 设置处理Unhandled Exception的回调函数
    SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);

    int *p = new int;
    *p = 10;

    std::cout << *p;

    delete p;

    *p = 100;

    std::cout << *p;
}

std::wstring FormatString(const wchar_t* fmt, ...)
{
    return std::wstring();
}
